package org.jdcenter.rmi.impl;

import java.net.MalformedURLException;
import java.rmi.RemoteException;
import java.rmi.registry.*;
import java.util.*;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdcenter.rmi.abs.*;

public class LocalServerFactory implements ServerFactory {
    private Log log = LogFactory.getLog(getClass());

    private Scheme context;
    private Map<Integer, RegistryObject> registry;

    private class RegistryObject {
        private int port;
        private int count;
		private Registry registry;  // It must be keep here

        public RegistryObject(int port, Registry registry) {
            this.port = port;
            this.count = 0;
            this.registry = registry;
        }

        public void increment() {
            this.count++;
        }

        public void decrement() {
            this.count--;
            if(this.count == 0) {
                LocalServerFactory.this.registry.remove(Integer.valueOf(port));
            }
        }
    }

    public LocalServerFactory(Scheme context) {
        this.context = context;
        this.registry = new HashMap<Integer, RegistryObject>();
    }

    public Scheme getContext() {
        return context;
    }

    public synchronized Server createAsync(String server, Object obj)
                throws URLException, ServerException {
        assert obj != null;

        try {
            log.info("Create server \"" + server + "\"");
            NamingURL url = NamingURL.parseURL(server);
            int port = url.getPort();
            register(port);

            return new LocalAsyncServer(String.format("//:%d/%s", port, url.getName()), obj, this);
        } catch (MalformedURLException e) {
            log.error(e);
            throw new URLException(e);
        } catch (RemoteException e) {
        	log.error(e);
            throw new ServerException(e);
        }
    }
    
    private void register(int port) throws RemoteException{
    	Integer key = Integer.valueOf(port);

        RegistryObject rgs = registry.get(key);
        if(rgs == null) {
            log.info("Create registry at port " + port);
            rgs = new RegistryObject(port, LocateRegistry.createRegistry(port));
            registry.put(key, rgs);
        }
        rgs.increment();
    }

    public synchronized void close(String server) {
        try {
            NamingURL url = NamingURL.parseURL(server);
            RegistryObject rgs = registry.get(Integer.valueOf(url.getPort()));
            if(url.isLocalHost() && rgs != null)
                rgs.decrement();
        } catch (MalformedURLException e) { }
    }
}

